import numpy as np
import datetime

class OptionMktPrice:
    def __init__(self, strike,bidPrice,askPrice):
        self.strike = strike
        self.bidPrice = bidPrice
        self.askPrice = askPrice
        if bidPrice != None and askPrice != None :
            self.midPrice = (bidPrice + askPrice)/2
        else:
            self.midPrice = None
        self.impVol=None


class CallPutPricePair:

    def __init__(self, strike, callPrice = None, putPrice = None):
        self.strike = strike
        self.callPrice = callPrice
        self.putPrice = putPrice



class OptionPriceChain:
    def __init__(self,expirationDate,callMktPriceArray, putMktPriceArray, pricingDate=None):
        self.expirationDate = expirationDate
        self.callMktPriceArray = callMktPriceArray
        self.putMktPriceArray = putMktPriceArray
        if pricingDate is None:
            pricingDate=datetime.date.today()
        self.pricingDate=pricingDate


        ##        if rInterest is None:
        ##            rInterest=0.0047     #This is the three month Libor at 5/4/2012
        ##        self.interestRate=rInterest

        self.createCallPutPairMap()

    def getXYTuplesForCalls(self):
        return self.getTestXYData()


    def getXYTuplesForPuts(self):
        return self.getTestXYData()

    def getCallMktPriceArray(self):
        return self.callMktPriceArray

    @staticmethod
    def getTestXYData():
        X = np.linspace(0,2*np.pi,50)
        Y = np.sin(X) + 0.1*np.random.normal( size=X.shape )
        return X, Y


    def createCallPutPairMap(self):
        self.callPutPairMap = dict()
        for callMktPrice in self.callMktPriceArray:
            val = self.callPutPairMap.get(callMktPrice.strike, None)
            if val is None:
                val = CallPutPricePair(callMktPrice.strike)
                val.strike =callMktPrice.strike
                self.callPutPairMap[callMktPrice.strike]=val

            val.callPrice = callMktPrice


        for putMktPrice in self.putMktPriceArray:
            val = self.callPutPairMap.get(putMktPrice.strike, None)
            if val is None:
                val = CallPutPricePair(callMktPrice.strike)
                val.strike =putMktPrice.strike
                self.callPutPairMap[putMktPrice.strike]=val

            val.putPrice = putMktPrice


    def getCallPutPairMap(self):
        return self.callPutPairMap


#    def _compare(self, other, method):
#        try:
#            return method(self.expirationDate, other._cmpkey())
#        except (AttributeError, TypeError):
#            # _cmpkey not implemented, or return different type,
#            # so I can't compare with "other".
#            return NotImplemented

#    def __lt__(self, other):
#        return self.expirationDate < other.expirationDate

#    def __le__(self, other):
#        return self._compare(other, lambda s, o: s <= o)
#
#    def __eq__(self, other):
#        return self._compare(other, lambda s, o: s == o)
#
#    def __ge__(self, other):
#        return self._compare(other, lambda s, o: s >= o)
#
#    def __gt__(self, other):
#        return self._compare(other, lambda s, o: s > o)
#
#    def __ne__(self, other):
#        return self._compare(other, lambda s, o: s != o)



class OptionMarketData:
    def __init__(self,optionPriceChainMap, pricingDate, refSpot, interestRate = 0.05) :
        self.optionPriceChainMap =optionPriceChainMap
        self.pricingDate = pricingDate
        self.refSpot = refSpot
        self.interestRate = interestRate



#    def getTestData(testExpDate):
    @staticmethod
    def getTestGSData(refSpot):

        optionPriceChainMap = dict()

        #Today=5/4/2012
        #GS S=108.99

        #Exp  Oct 19, 12

        expDate=datetime.date(2012,10,19);

        callPriceArray = []
        putPriceArray = []

        callPrice = OptionMktPrice(65,44.2,45.2)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(80,30.2,31.45)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(90,21.1,23.45)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(95,17.8,18.1)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(100,14.2,14.4)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(105,11.05,11.2)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(110,8.3,8.45)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(115,6,6.15)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(120,4.15,4.3)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(125,2.8,2.89)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(130,1.79,1.87)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(135,1.15,1.19)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(140,0.69,0.75)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(145,0.41,0.46)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(150,0.29,0.32)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(155,0.14,0.21)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(160,0.08,0.15)
        callPriceArray.append(callPrice)


        pricingDate=datetime.date(2012,5,4)
        optionPriceChain = OptionPriceChain(expDate, callPriceArray, putPriceArray, pricingDate)
        optionPriceChainMap[expDate] = optionPriceChain



        #========== Jul 20 2012

        expDate=datetime.date(2012,7,20);

        callPriceArray = []
        putPriceArray = []


        callPrice = OptionMktPrice(45,62.6,65.85)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(60,47.65,50.6)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(70,38.4,40.65)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(75,33.2,35.7)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(80,28.6,30.85)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(85,24.45,25)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(90,19.85,20)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(95,15.5,15.65)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(100,11.55,11.65)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(105,8.05,8.2)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(110,5.25,5.35)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(115,3.1,3.2)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(120,1.7,1.75)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(125,0.85,0.89)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(130,0.4,0.44)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(135,0.22,0.25)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(140,0.12,0.15)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(145,0.04,0.09)
        callPriceArray.append(callPrice)

        optionPriceChain = OptionPriceChain(expDate, callPriceArray, putPriceArray, datetime.date(2012,5,4))
        optionPriceChainMap[expDate] = optionPriceChain

        testData = OptionMarketData(optionPriceChainMap, datetime.date(2012,5,4), refSpot)

        return testData



    @staticmethod
    def getTestGSData2(refSpot):
        optionPriceChainMap = dict()
        #expDate=7/12/2012

        #=================

        expDate=datetime.date(2012,6,15);

        callPriceArray = []
        putPriceArray = []

        callPrice = OptionMktPrice(70,38.85,40.75)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(95,15.30,15.45)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(100.00,10.85,11.00)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(105.00,6.90,7.05)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(110,3.85,3.95)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(115,1.81,1.84)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(120,0.71,0.73)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(125,0.25,0.27)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(130,0.08,0.11)
        callPriceArray.append(callPrice)




        putPrice = OptionMktPrice(70,0.06,0.11)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(80,0.17,0.2)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(85,0.27,0.31)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(90,0.44,0.47)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(95,0.77,0.8)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(100,1.4,1.42)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(105,2.52,2.56)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(110,4.4,4.5)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(115,7.4,7.5)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(120,11.3,11.4)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(125,15.75,15.9)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(130,20.65,20.8)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(135,25.55,25.7)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(140,29.9,31.6)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(150,40.5,41.6)
        putPriceArray.append(putPrice)



        optionPriceChain = OptionPriceChain(expDate, callPriceArray, putPriceArray, pricingDate=datetime.date.today())
        optionPriceChainMap[expDate] = optionPriceChain

        #=================


        #=================

        expDate=datetime.date(2012,7,20);

        callPriceArray = []
        putPriceArray = []


        callPrice = OptionMktPrice(70,39.35,40.8)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(75,34.5,35.9)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(80,29.45,30.8)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(85,25.15,25.7)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(90,20.95,21.1)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(95,16.55,16.7)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(100,12.45,12.6)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(105,8.8,8.95)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(110,5.85,5.95)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(115,3.55,3.6)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(120,1.95,1.99)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(125,0.97,1)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(130,0.46,0.48)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(135,0.2,0.26)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(140,0.1,0.15)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(150,0.01,0.06)
        callPriceArray.append(callPrice)





        putPrice = OptionMktPrice(70,0.21,0.27)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(75,0.32,0.37)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(80,0.48,0.51)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(85,0.73,0.77)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(90,1.14,1.17)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(95,1.74,1.78)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(100,2.66,2.71)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(105,4,4.1)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(110,6,6.1)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(115,8.65,8.75)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(120,12.05,12.2)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(125,16.05,16.2)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(130,20.5,20.7)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(135,25.3,25.45)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(140,30.2,30.4)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(145,35.1,36.2)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(150,39.7,41.35)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(155,44.2,47)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(160,50.15,51.25)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(165,54.1,56.2)
        putPriceArray.append(putPrice)


        optionPriceChain = OptionPriceChain(expDate, callPriceArray, putPriceArray, pricingDate=datetime.date.today())
        optionPriceChainMap[expDate] = optionPriceChain

        #=================





        #=================

        expDate=datetime.date(2012,10,19);

        callPriceArray = []
        putPriceArray = []


        callPrice = OptionMktPrice(80,30.9,32.25)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(90,21.2,23.45)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(95,18.45,19.1)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(100,15.25,15.4)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(105,11.85,11.95)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(110,9,9.15)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(115,6.55,6.7)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(120,4.6,4.7)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(125,3.05,3.15)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(130,1.96,2.02)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(135,1.21,1.28)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(140,0.73,0.78)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(145,0.43,0.47)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(150,0.25,0.3)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(155,0.14,0.2)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(155,0.14,0.2)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(160,0.08,0.14)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(165,0.03,0.1)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(170,0.01,0.12)
        callPriceArray.append(callPrice)


        putPrice = OptionMktPrice(70,0.88,0.92)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(75,1.21,1.26)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(80,1.67,1.73)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(85,2.29,2.34)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(90,3.1,3.15)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(95,4.1,4.2)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(100,5.45,5.55)

        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(105,7.1,7.2)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(110,9.25,9.4)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(100,2.66,2.71)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(115,11.75,11.9)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(110,6,6.1)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(115,8.65,8.75)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(120,14.75,14.9)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(125,18.25,18.45)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(130,22.25,22.4)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(135,26.35,26.55)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(140,30.65,32.25)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(145,34.8,37.4)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(150,39.85,41.6)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(155,44.5,47.1)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(160,50.15,51.25)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(165,54.1,56.2)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(170,59.15,62.05)
        putPriceArray.append(putPrice)

        optionPriceChain = OptionPriceChain(expDate, callPriceArray, putPriceArray, pricingDate=datetime.date.today())
        optionPriceChainMap[expDate] = optionPriceChain

        #=================

        #=================

        expDate=datetime.date(2013,1,18);

        callPriceArray = []
        putPriceArray = []


        callPrice = OptionMktPrice(70,39.9,42.05)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(75,35.4,37.6)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(80,32.75,32.95)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(85,28.6,28.85)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(90,24.65,24.85)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(95,20.85,21.05)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(100,17.4,17.6)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(105,14.2,14.4)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(110,11.4,11.55)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(115,8.85,9.05)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(120,6.7,6.85)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(125,5.05,5.2)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(130,3.65,3.8)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(135,2.6,2.7)
        callPriceArray.append(callPrice)

        callPrice = OptionMktPrice(140,1.79,1.89)
        callPriceArray.append(callPrice)


        putPrice = OptionMktPrice(70,1.95,2.02)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(75,2.48,2.56)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(80,3.15,3.3)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(85,4.05,4.15)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(90,5.05,5.2)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(95,6.3,6.45)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(100,7.85,8)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(105,9.7,9.8)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(110,11.8,11.95)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(115,14.35,14.55)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(120,17.2,17.4)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(125,20.5,20.7)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(130,24.05,24.25)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(135,28,28.25)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(140,32.2,32.45)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(145,36.15,37.95)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(150,40.85,42.5)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(155,45.15,47.8)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(160,50.05,51.9)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(165,54.7,57.4)
        putPriceArray.append(putPrice)

        putPrice = OptionMktPrice(170,59.75,61.7)
        putPriceArray.append(putPrice)

        optionPriceChain = OptionPriceChain(expDate, callPriceArray, putPriceArray, pricingDate=datetime.date.today())
        optionPriceChainMap[expDate] = optionPriceChain

        testData = OptionMarketData(optionPriceChainMap, datetime.date.today(), refSpot)

        return testData


        #=================






#    td=GetTestData()
#    vsfTest=vsf.VolSurfaceFitter(108.99,0.0047,td)
#
#    #paramsWithVatm=[T,S,r,Vatm, parameters[0],parameters[1],parameters[2] ]
#    mMatrixFitted=vsfTest.fitParametricVolSurface()
#
#    pvs=vs.ParametricVolSurface(mMatrixFitted)
#    pvs.lookupVolatility(100,.4)



    #    @staticmethod
#    def getTestData(testExpDate):
#
#        callPriceArray = []
#        putPriceArray = []
#
#        callPrice = OptionMktPrice(1200, 1.5, 2.5)
#        putPrice = OptionMktPrice(1200, 0.5, 7.5)
#        callPriceArray.append(callPrice)
#        putPriceArray.append(putPrice)
#
#        optionPriceChainMap = dict()
#        optionPriceChain = OptionPriceChain(testExpDate, callPriceArray, putPriceArray)
#        optionPriceChainMap[testExpDate] = optionPriceChain
#
#        nextMonthDate = datetime.date(testExpDate.year, testExpDate.month+1, 1)
#        optionPriceChainMap[nextMonthDate] = optionPriceChain
#
#        testData = OptionMarketData(optionPriceChainMap)
#
#        return testData

